package com.kyleswebspace.propertyanalyzer.gui;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedList;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.OrientationRequested;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.ToolTipManager;

import com.kyleswebspace.propertyanalyzer.config.ColorBox;
import com.kyleswebspace.propertyanalyzer.model.DataModel;

public class BaseFrame extends JFrame implements ActionListener, Printable,
		Pageable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 713777234700179249L;

	private DataModel dm;
	private FocusMediator fm;

	private MainPanel mp;

	private Image windowIcon;

	JFileChooser fileChooser;

	JMenuBar menuBar;
	JMenu fileMenu, tablesMenu, helpMenu, overrideMenu;
	JMenuItem saveItem, saveAsItem, openItem, exitItem, printItem, resetItem;
	JMenuItem approxTables, cmhcTables, xferTaxTables;
	JMenuItem helpItem;
	JCheckBoxMenuItem overrideAppraisal, overrideLegalFees, overrideInspection,
			overrideLandXferTax, overrideRent, overrideMaintenance,
			overrideManagement, overrideLoanA, overrideLoanB, overrideLoanC,
			overrideCMHCA, overrideCMHCB, overrideCMHCC;

	public BaseFrame(DataModel dm, FocusMediator fm) {
		this.dm = dm;
		this.fm = fm;

		fileChooser = new JFileChooser();

		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		ToolTipManager.sharedInstance().setDismissDelay(15000);
		ToolTipManager.sharedInstance().setInitialDelay(5);

		loadIcon();
		this.setIconImage(windowIcon);

		// create the menu bar
		menuBar = new JMenuBar();

		// File Menu
		fileMenu = new JMenu("File");
		fileMenu.setMnemonic(KeyEvent.VK_F);
		saveItem = new JMenuItem("Save");
		saveItem.addActionListener(this);
		// saveAsItem = new JMenuItem("Save As...");
		// saveAsItem.addActionListener(this);
		openItem = new JMenuItem("Open");
		openItem.addActionListener(this);
		printItem = new JMenuItem("Print");
		printItem.addActionListener(this);
		exitItem = new JMenuItem("Exit");
		exitItem.addActionListener(this);
		resetItem = new JMenuItem("Reset");
		resetItem.addActionListener(this);
		fileMenu.add(resetItem);
		fileMenu.addSeparator();
		fileMenu.add(openItem);
		fileMenu.addSeparator();
		fileMenu.add(saveItem);
		// fileMenu.add(saveAsItem);
		fileMenu.addSeparator();
		fileMenu.add(printItem);
		fileMenu.addSeparator();
		fileMenu.add(exitItem);
		menuBar.add(fileMenu);

		// Tables Menu
		tablesMenu = new JMenu("Tables");
		tablesMenu.setMnemonic(KeyEvent.VK_T);
		approxTables = new JMenuItem("Fee Approximation Tables");
		approxTables.addActionListener(this);
		cmhcTables = new JMenuItem("CMHC Tables");
		cmhcTables.addActionListener(this);
		xferTaxTables = new JMenuItem("Land Transfer Tax Table");
		xferTaxTables.addActionListener(this);
		tablesMenu.add(approxTables);
		tablesMenu.add(cmhcTables);
		tablesMenu.add(xferTaxTables);
		menuBar.add(tablesMenu);

		// Override Menu
		overrideMenu = new JMenu("Overrides");
		overrideMenu.setMnemonic(KeyEvent.VK_O);

		overrideAppraisal = new JCheckBoxMenuItem("Appraisal");
		fm.setAppraisalOverride(overrideAppraisal);
		overrideAppraisal.addActionListener(this);

		overrideLegalFees = new JCheckBoxMenuItem("Legal Fees");
		fm.setLegalFeesOverride(overrideLegalFees);
		overrideLegalFees.addActionListener(this);

		overrideInspection = new JCheckBoxMenuItem("Inspection");
		fm.setInspectionOverride(overrideInspection);
		overrideInspection.addActionListener(this);

		overrideLandXferTax = new JCheckBoxMenuItem("Land Transfer Tax");
		fm.setLandXferTaxOverride(overrideLandXferTax);
		overrideLandXferTax.addActionListener(this);

		overrideRent = new JCheckBoxMenuItem("Rent");
		fm.setRentOverride(overrideRent);
		overrideRent.addActionListener(this);

		overrideMaintenance = new JCheckBoxMenuItem("Maintenance");
		fm.setMaintenanceOverride(overrideMaintenance);
		overrideMaintenance.addActionListener(this);

		overrideManagement = new JCheckBoxMenuItem("Management");
		fm.setManagementOverride(overrideManagement);
		overrideManagement.addActionListener(this);

		overrideLoanA = new JCheckBoxMenuItem("Loan Amount (Mort #1)");
		fm.setLoanOverrideA(overrideLoanA);
		overrideLoanA.addActionListener(this);

		overrideLoanB = new JCheckBoxMenuItem("Loan Amount (Mort #2)");
		fm.setLoanOverrideB(overrideLoanB);
		overrideLoanB.addActionListener(this);

		overrideLoanC = new JCheckBoxMenuItem("Loan Amount (Mort #3)");
		fm.setLoanOverrideC(overrideLoanC);
		overrideLoanC.addActionListener(this);

		overrideCMHCA = new JCheckBoxMenuItem("CMHC Fee (Mort #1)");
		fm.setCmhcOverrideA(overrideCMHCA);
		overrideCMHCA.addActionListener(this);

		overrideCMHCB = new JCheckBoxMenuItem("CMHC Fee (Mort #2)");
		fm.setCmhcOverrideB(overrideCMHCB);
		overrideCMHCB.addActionListener(this);

		overrideCMHCC = new JCheckBoxMenuItem("CMHC Fee (Mort #3)");
		fm.setCmhcOverrideC(overrideCMHCC);
		overrideCMHCC.addActionListener(this);

		if (dm.isOverrideAppraisal())
			overrideAppraisal.setSelected(true);
		if (dm.isOverrideLegalFees())
			overrideLegalFees.setSelected(true);
		if (dm.isOverrideInspection())
			overrideInspection.setSelected(true);
		if (dm.isOverrideLandXferTax())
			overrideLandXferTax.setSelected(true);
		if (dm.isOverrideRent())
			overrideRent.setSelected(true);
		if (dm.isOverrideMaintenance())
			overrideMaintenance.setSelected(true);
		if (dm.isOverrideManagement())
			overrideManagement.setSelected(true);
		if (dm.isOverrideLoanAmountA())
			overrideLoanA.setSelected(true);
		if (dm.isOverrideLoanAmountB())
			overrideLoanB.setSelected(true);
		if (dm.isOverrideLoanAmountC())
			overrideLoanC.setSelected(true);
		if (dm.isOverrideCMHCA())
			overrideCMHCA.setSelected(true);
		if (dm.isOverrideCMHCB())
			overrideCMHCB.setSelected(true);
		if (dm.isOverrideCMHCC())
			overrideCMHCC.setSelected(true);

		overrideMenu.add(overrideAppraisal);
		overrideMenu.add(overrideCMHCA);
		overrideMenu.add(overrideCMHCB);
		overrideMenu.add(overrideCMHCC);
		overrideMenu.add(overrideInspection);
		overrideMenu.add(overrideLegalFees);
		overrideMenu.add(overrideLoanA);
		overrideMenu.add(overrideLoanB);
		overrideMenu.add(overrideLoanC);
		overrideMenu.add(overrideLandXferTax);
		overrideMenu.add(overrideMaintenance);
		overrideMenu.add(overrideManagement);
		overrideMenu.add(overrideRent);

		menuBar.add(overrideMenu);

		// Help Menu
		helpMenu = new JMenu("Help");
		helpMenu.setMnemonic(KeyEvent.VK_H);
		helpItem = new JMenuItem("Instructions");
		helpItem.addActionListener(this);
		helpMenu.add(helpItem);
		menuBar.add(helpMenu);

		this.setJMenuBar(menuBar);

		mp = new MainPanel(dm, fm);
		this.add(mp);

		// this.setSize(800, 700);
		this.pack();
		this.setTitle("Arca Property Analyzer v1.2");
		this.setLocationRelativeTo(null);
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == exitItem) {
			System.exit(0);
		} else if (e.getSource() == approxTables) {
			ApproxTablesFrame approxTablesFrame = new ApproxTablesFrame(dm);
			approxTablesFrame.setVisible(true);
		} else if (e.getSource() == cmhcTables) {
			CHMCTablesFrame chmcTablesFrame = new CHMCTablesFrame(dm);
			chmcTablesFrame.setVisible(true);
		} else if (e.getSource() == xferTaxTables) {
			LandXferTaxFrame landXferTaxFrame = new LandXferTaxFrame(dm);
			landXferTaxFrame.setVisible(true);
		} else if (e.getSource() == helpItem) {
			JOptionPane
					.showMessageDialog(
							this,

							"<html><font size='2'>"
									+ "</b>This property analyzer is designed to help you make an educated decision about purchasing a property.<br/>"
									+ "It is not intended that this analyzer will actually make the decision for you.<br/>"
									+ "<u>ARCA Real Estate Investments Inc. assumes no responsibility for any decisions the user of this program<br/>"
									+ "makes based upon the information either contained in or generated by this analyzer.</u><br/><br/>"
									+ "1. To begin you would enter the property information in the Top left box of the analyzer. The cells highlighted in light blue are where you will enter your data. If you have questions just place the cursor over the<br/>"
									+ "appropriate cell with a darkened border and an information box should open for you. When you first input data you will use the same value for the Asking price and the purchase price. Once all data has been<br/>"
									+ "input you can then adjust the purchase price in order to achieve your desired outcome in the key indicator box.<br/><br/>"
									+ "2. You would then input the \"Income\" information in the box to the right of the \"Property Information\".<br/><br/>"
									+ "3. Below the \"Income\" box you will find the \"Expense\" box. There will be many unanswered expenses here because very rarely will you be given all of the related expenses initially. Therefore you may have to make some<br/>"
									+ "assumptions in order to provide you with a more realistic financial picture for this property. As you discover the real values you can go back and update the numbers in your original spreadsheet. If the expenses listed<br/>"
									+ "don't apply to your property then leave them empty or if you have an expense or two that are not listed then you can enter them under \"other\".<br/><br/>"
									+ "4. Next you will look at the \"Financing\" box. You will enter the deatils of the 1st, 2nd and 3rd mortgages if applicable. Under the column for Mort #1 you will find all the details relating to that mortgage. If this is a single<br/>"
									+ "family home or up to four units then you can enter up to 80% in cell Q2 without having to apply for insurance. If you want to borrow more than 80% you would then need to click yes in box Q9 in order to calculate the<br/>"
									+ "insurance premium. For commercial properties greater than four units you can avoid mortgage insurance if your % of purchase price is less than 60 or 65%. If you want more than the 60 or65% you would enter a value<br/>"
									+ "of up to 85% but you would then have to click the yes button for mortgage insurance. Any secondary financing such as a second mortgage or VTB (vendor held mortgage) would be entered under Mort #2 and very rarely<br/>"
									+ "will there be any mortgage insurance. VTB's are very often calculated with interest payments only and if this is the case then when you highlight cell R5 you would click on interest only. The amortization period is the<br/>"
									+ "lifespan of the mortgage and is only relevant when a mortgage has a principle and interest payment because this number will help calculate the payment based upon the lifespan of the mortgae. If you are using your own<br/>"
									+ "line of credit for some or all of the down payment then I would suggest you enter this amount as a 3rd mortgage because in reality it is borrowed money. If you are outside of Canada using this analyzer and you are using<br/>"
									+ "insured financing then you will have to manually insert what the insurance fees will be because this analyzer automatically claculates the premium based upon CMHC rates.<br/><br/>"
									+ "5. Now we look at the actual \"Purchase Costs\" where you will find values already inserted by default for items such as Appraisal, Legal, Inspection and Land Transfer Tax. You will make adjustments to these values if you<br/>"
									+ "know the real numbers related to your deal. The default numbers are just guidelines to use but should be verified because these numbers may vary greatly from region to region.<br/><br/>"
									+ "6. You can now study the outcome in the \"Key Indicator\" box to determine what kind of deal you have. Keep in mind that the target goals are my personal goals which work for me. These goals are personal and may vary<br/>"
									+ "from deal to deal depending on your personal expectations. If your actual numbers are not yielding satisfactory results then you can look back at all the values to ensure you entered them correctly and then analyze what<br/>"
									+ "you can do with this property. Are you able to decrease expenses, increase income, get better finance terms and lastly lower the sale price. If after making all these adjustments then maybe the deal just won't work and<br/>"
									+ "you move on." + "</font></html>",

							"Instructions", JOptionPane.PLAIN_MESSAGE);
		} else if (e.getSource() == overrideAppraisal) {
			if (!overrideAppraisal.isSelected() == true) {
				dm.setOverrideAppraisal(false);
				fm.getAppraisalField().setBackground(ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideAppraisal.setSelected(false);
			}
		} else if (e.getSource() == overrideLegalFees) {
			if (!overrideLegalFees.isSelected() == true) {
				dm.setOverrideLegalFees(false);
				fm.getLegalFeesField().setBackground(ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideLegalFees.setSelected(false);
			}
		} else if (e.getSource() == overrideInspection) {
			if (!overrideInspection.isSelected() == true) {
				dm.setOverrideInspection(false);
				fm.getInspectionField()
						.setBackground(ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideInspection.setSelected(false);
			}
		} else if (e.getSource() == overrideLandXferTax) {
			if (!overrideLandXferTax.isSelected() == true) {
				dm.setOverrideLandXferTax(false);
				fm.getLandXferTaxField().setBackground(
						ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideLandXferTax.setSelected(false);
			}
		} else if (e.getSource() == overrideRent) {
			if (!overrideRent.isSelected() == true) {
				dm.setOverrideRent(false);
				fm.getRentField().setBackground(
						ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideRent.setSelected(false);
			}
		} else if (e.getSource() == overrideMaintenance) {
			if (!overrideMaintenance.isSelected() == true) {
				dm.setOverrideMaintenance(false);
				fm.getMaintenanceFieldB().setBackground(
						ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideMaintenance.setSelected(false);
			}
		} else if (e.getSource() == overrideManagement) {
			if (!overrideManagement.isSelected() == true) {
				dm.setOverrideManagement(false);
				fm.getManagementFieldB()
						.setBackground(ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideManagement.setSelected(false);
			}
		} else if (e.getSource() == overrideLoanA) {
			if (!overrideLoanA.isSelected() == true) {
				dm.setOverrideLoanAmountA(false);
				fm.getLoanAmountAField().setBackground(
						ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideLoanA.setSelected(false);
			}
		} else if (e.getSource() == overrideLoanB) {
			if (!overrideLoanB.isSelected() == true) {
				dm.setOverrideLoanAmountB(false);
				fm.getLoanAmountBField().setBackground(
						ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideLoanB.setSelected(false);
			}
		} else if (e.getSource() == overrideLoanC) {
			if (!overrideLoanC.isSelected() == true) {
				dm.setOverrideLoanAmountC(false);
				fm.getLoanAmountCField().setBackground(
						ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideLoanC.setSelected(false);
			}
		} else if (e.getSource() == overrideCMHCA) {
			if (!overrideCMHCA.isSelected() == true) {
				dm.setOverrideCMHCA(false);
				fm.getCmhcFeeFieldA().setBackground(ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideCMHCA.setSelected(false);
			}
		} else if (e.getSource() == overrideCMHCB) {
			if (!overrideCMHCB.isSelected() == true) {
				dm.setOverrideCMHCB(false);
				fm.getCmhcFeeFieldB().setBackground(ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideCMHCB.setSelected(false);
			}
		} else if (e.getSource() == overrideCMHCC) {
			if (!overrideCMHCC.isSelected() == true) {
				dm.setOverrideCMHCC(false);
				fm.getCmhcFeeFieldC().setBackground(ColorBox.overridableColor);
				dm.updateInterface();
			} else {
				JOptionPane.showConfirmDialog(this,
						"To override a field, please click it and modify it.",
						"Override", JOptionPane.DEFAULT_OPTION);

				overrideCMHCC.setSelected(false);
			}
		} else if (e.getSource() == saveItem) {
			fileChooser.showSaveDialog(null);

			try {
				ObjectOutputStream out = new ObjectOutputStream(
						new BufferedOutputStream(new FileOutputStream(
								fileChooser.getSelectedFile())));
				// avoid unserializable exception
				this.windowIcon = null;
				out.writeObject(dm);
				out.flush();
				out.close();
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
		} else if (e.getSource() == openItem) {
			fileChooser.showOpenDialog(null);

			try {
				ObjectInputStream in = new ObjectInputStream(
						new BufferedInputStream(new FileInputStream(fileChooser
								.getSelectedFile())));
				this.dm = (DataModel) in.readObject();

				
				BaseFrame bf = new BaseFrame(dm, fm);
				bf.setResizable(false);
				bf.setVisible(true);

				dm.updateInterface();
				
				this.dispose();
				
			} catch (Exception ee) {
				ee.printStackTrace();
			}
		} else if (e.getSource() == resetItem) {
			dm.reset();

		} else if (e.getSource() == printItem) {
			printGUI();
		}
	}

	private void loadIcon() {
		this.windowIcon = new ImageIcon(getClass().getResource("arcaIcon.png"))
				.getImage();
	}

	private void printGUI() {
		PrinterJob job = PrinterJob.getPrinterJob();
		job.setPageable(this);
		boolean doPrint = job.printDialog();

		if (doPrint) {
			try {
				job.print();
			} catch (PrinterException e) {
				/* The job did not successfully complete */
			}
		}

	}

	public int print(Graphics g, PageFormat pf, int page)
			throws PrinterException {
		if (page > 0) {
			return NO_SUCH_PAGE;
		}

		Graphics2D g2d = (Graphics2D) g;
		g2d.translate(pf.getImageableX(), pf.getImageableY());
		g2d.scale(0.60, 0.60);

		/* Print the entire visible contents of a java.awt.Frame */
		this.printAll(g);

		return PAGE_EXISTS;
	}

	@Override
	public int getNumberOfPages() {
		return 1;
	}

	@Override
	public PageFormat getPageFormat(int pageIndex)
			throws IndexOutOfBoundsException {
		PageFormat pf = new PageFormat();
		pf.setOrientation(PageFormat.LANDSCAPE);
		return pf;
	}

	@Override
	public Printable getPrintable(int pageIndex)
			throws IndexOutOfBoundsException {
		return this;
	}

}
